package org.hawk.gwt.ppc.parser.impl;

import org.hawk.gwt.ppc.parser.DescriptorVisitor;
import org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor;
import org.hawk.gwt.ppc.parser.Token;
import org.hawk.gwt.ppc.utils.PreprocessorException;

/**
 * Implementation for literals.
 * 
 * @author alex.bereznevatiy@gmail.com
 *
 */
final class LiteralExpressionDescriptorImpl extends AbstractExpressionDescriptor
		implements LiteralExpressionDescriptor {
	private Token token;
	
	LiteralExpressionDescriptorImpl(Token token) {
		super(token, token);
		this.token = token;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#getType()
	 */
	public Class<?> getType() {
		if (token.isStringLiteral()) {
			return String.class;
		}
		if (token.isCharacterLiteral()) {
			return Character.class;
		}
		char signChar = token.charAt(token.length() - 1);
		if (signChar == 'l' || signChar == 'L') {
			return Long.class;
		}
		if (token.length() > 1 && (token.charAt(1) == 'x' || token.charAt(1) == 'X')) {
			return Integer.class;
		}
		if (signChar == 'd' || signChar == 'D') {
			return Double.class;
		}
		if (signChar == 'f' || signChar == 'F') {
			return Float.class;
		}
		final int length = token.length();
		for (int i = 0; i < length; i++) {
			char c = token.charAt(i);
			if (c == 'e' || c == 'E' || c == '.') {
				return Double.class;
			}
		}
		return Integer.class;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#asString()
	 */
	public String asString() {
		if (token.isStringLiteral() || token.isCharacterLiteral()) {
			return (String)token.subSequence(1, token.length() - 1);
		}
		return token.toString();
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#asChar()
	 */
	public char asChar() throws IllegalStateException {
		if (!token.isCharacterLiteral()) {
			throw new IllegalStateException("Not a character");
		}
		if (token.length() == 3) {
			return token.charAt(1);
		}
		if (token.length() == 8 && token.charAt(2) == 'u') {
			return (char) Integer.parseInt(token.subSequence(3, token.length() - 1).toString(), 16);
		}
		throw new IllegalStateException("Not a character");
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#asInt()
	 */
	public int asInt() throws NumberFormatException {
		return Integer.parseInt(token.toString());
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#asFloat()
	 */
	public float asFloat() throws NumberFormatException {
		return Float.parseFloat(token.toString());
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#asDouble()
	 */
	public double asDouble() throws NumberFormatException {
		return Double.parseDouble(token.toString());
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.LiteralExpressionDescriptor#asLong()
	 */
	public long asLong() throws NumberFormatException {
		char c = token.charAt(token.length() - 1);
		if (c == 'l' || c == 'L') {
			return Long.parseLong(token.subSequence(0, token.length() - 1).toString());
		}
		return Long.parseLong(token.toString());
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.parser.Descriptor#visit(org.hawk.gwt.ppc.parser.DescriptorVisitor)
	 */
	public void visit(DescriptorVisitor visitor) throws PreprocessorException {
		visitor.visit(this);
	}
}
